home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / binutils.252 / gas / as.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-10-19  |  14.2 KB  |  586 lines

  1. /* as.c - GAS main program.
  2.    Copyright (C) 1987, 1990, 1991, 1992, 1994 Free Software Foundation, Inc.
  3.  
  4.    This file is part of GAS, the GNU Assembler.
  5.  
  6.    GAS is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 2, or (at your option)
  9.    any later version.
  10.  
  11.    GAS is distributed in the hope that it will be useful,
  12.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.    GNU General Public License for more details.
  15.  
  16.    You should have received a copy of the GNU General Public License
  17.    along with GAS; see the file COPYING.  If not, write to
  18.    the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
  19.  
  20. /*
  21.  * Main program for AS; a 32-bit assembler of GNU.
  22.  * Understands command arguments.
  23.  * Has a few routines that don't fit in other modules because they
  24.  * are shared.
  25.  *
  26.  *
  27.  *            bugs
  28.  *
  29.  * : initialisers
  30.  *    Since no-one else says they will support them in future: I
  31.  * don't support them now.
  32.  *
  33.  */
  34.  
  35. #include "ansidecl.h"
  36. #include "libiberty.h"
  37.  
  38. #define COMMON
  39.  
  40. #include "as.h"
  41. #include "subsegs.h"
  42. #include "output-file.h"
  43.  
  44. #include <signal.h>
  45.  
  46. #ifndef SIGTY
  47. #ifdef __STDC__
  48. #define SIGTY void
  49. #else
  50. #define SIGTY int
  51. #endif /* __STDC__ */
  52. #endif /* SIGTY */
  53.  
  54. #if 0
  55. /* Not currently used.  */
  56. static SIGTY got_sig PARAMS ((int sig));
  57. #endif
  58. static void perform_an_assembly_pass PARAMS ((int argc, char **argv));
  59.  
  60. int listing;            /* true if a listing is wanted */
  61.  
  62. char *myname;            /* argv[0] */
  63. #ifdef BFD_ASSEMBLER
  64. segT reg_section, expr_section;
  65. segT text_section, data_section, bss_section;
  66. #endif
  67.  
  68.  
  69. void
  70. print_version_id ()
  71. {
  72.   static int printed;
  73.   if (printed)
  74.     return;
  75.   printed = 1;
  76.  
  77.   fprintf (stderr, "GNU assembler version %s (%s)", GAS_VERSION, TARGET_ALIAS);
  78. #ifdef BFD_ASSEMBLER
  79.   fprintf (stderr, ", using BFD version %s", BFD_VERSION);
  80. #endif
  81.   fprintf (stderr, "\n");
  82. }
  83.  
  84. void
  85. show_usage (stream)
  86.      FILE *stream;
  87. {
  88.   fprintf (stream, "Usage: %s [option...] [asmfile...]\n", myname);
  89.  
  90.   fprintf (stream, "\
  91. Options:\n\
  92. -a[sub-option...]    turn on listings\n\
  93.   Sub-options [default hls]:\n\
  94.   d    omit debugging directives\n\
  95.   h    include high-level source\n\
  96.   l    include assembly\n\
  97.   n    omit forms processing\n\
  98.   s    include symbols\n");
  99.   fprintf (stream, "\
  100. -D            produce assembler debugging messages\n\
  101. -f            skip whitespace and comment preprocessing\n\
  102. --help            show this message and exit\n\
  103. -I DIR            add DIR to search list for .include directives\n\
  104. -J            don't warn about signed overflow\n\
  105. -K            warn when differences altered for long displacements\n\
  106. -L            keep local symbols (starting with `L')\n");
  107.   fprintf (stream, "\
  108. -nocpp            ignored\n\
  109. -o OBJFILE        name the object-file output OBJFILE (default a.out)\n\
  110. -R            fold data section into text section\n\
  111. --statistics        print maximum bytes and total seconds used\n\
  112. --version        print assembler version number and exit\n\
  113. -W            suppress warnings\n\
  114. -w            ignored\n\
  115. -X            ignored\n\
  116. -Z            generate object file even after errors\n");
  117.  
  118.   md_show_usage (stream);
  119. }
  120.  
  121. /*
  122.  * Since it is easy to do here we interpret the special arg "-"
  123.  * to mean "use stdin" and we set that argv[] pointing to "".
  124.  * After we have munged argv[], the only things left are source file
  125.  * name(s) and ""(s) denoting stdin. These file names are used
  126.  * (perhaps more than once) later.
  127.  *
  128.  * check for new machine-dep cmdline options in
  129.  * md_parse_option definitions in config/tc-*.c
  130.  */
  131.  
  132. void
  133. parse_args (pargc, pargv)
  134.      int *pargc;
  135.      char ***pargv;
  136. {
  137.   int old_argc, new_argc;
  138.   char **old_argv, **new_argv;
  139.  
  140.   /* Starting the short option string with '-' is for programs that
  141.      expect options and other ARGV-elements in any order and that care about
  142.      the ordering of the two.  We describe each non-option ARGV-element
  143.      as if it were the argument of an option with character code 1.  */
  144.  
  145.   char *shortopts;
  146.   extern CONST char *md_shortopts;
  147. #ifdef VMS
  148.   /* -v takes an argument on VMS, so we don't make it a generic option.  */
  149.   CONST char *std_shortopts = "-JKLRWZfa::DI:o:wX";
  150. #else
  151.   CONST char *std_shortopts = "-JKLRWZfa::DI:o:vwX";
  152. #endif
  153.  
  154.   struct option *longopts;
  155.   extern struct option md_longopts[];
  156.   extern size_t md_longopts_size;
  157.   static const struct option std_longopts[] = {
  158. #define OPTION_HELP (OPTION_STD_BASE)
  159.     {"help", no_argument, NULL, OPTION_HELP},
  160. #define OPTION_NOCPP (OPTION_STD_BASE + 1)
  161.     {"nocpp", no_argument, NULL, OPTION_NOCPP},
  162. #define OPTION_STATISTICS (OPTION_STD_BASE + 2)
  163.     {"statistics", no_argument, NULL, OPTION_STATISTICS},
  164. #define OPTION_VERSION (OPTION_STD_BASE + 3)
  165.     {"version", no_argument, NULL, OPTION_VERSION},
  166. #define OPTION_DUMPCONFIG (OPTION_STD_BASE + 4)
  167.     {"dump-config", no_argument, NULL, OPTION_DUMPCONFIG},
  168. #define OPTION_VERBOSE (OPTION_STD_BASE + 5)
  169.     {"verbose", no_argument, NULL, OPTION_VERBOSE},
  170.   };
  171.  
  172.   /* Construct the option lists from the standard list and the
  173.      target dependent list.  */
  174.   shortopts = concat (std_shortopts, md_shortopts, (char *) NULL);
  175.   longopts = (struct option *) xmalloc (sizeof (std_longopts) + md_longopts_size);
  176.   memcpy (longopts, std_longopts, sizeof (std_longopts));
  177.   memcpy ((char *) longopts + sizeof (std_longopts),
  178.       md_longopts, md_longopts_size);
  179.  
  180.   /* Make a local copy of the old argv.  */
  181.   old_argc = *pargc;
  182.   old_argv = *pargv;
  183.  
  184.   /* Initialize a new argv that contains no options.  */
  185.   new_argv = (char **) xmalloc (sizeof (char *) * (old_argc + 1));
  186.   new_argv[0] = old_argv[0];
  187.   new_argc = 1;
  188.   new_argv[new_argc] = NULL;
  189.  
  190.   while (1)
  191.     {
  192.       /* getopt_long_only is like getopt_long, but '-' as well as '--' can
  193.      indicate a long option.  */
  194.       int longind;
  195.       int optc = getopt_long_only (old_argc, old_argv, shortopts, longopts,
  196.                    &longind);
  197.  
  198.       if (optc == -1)
  199.     break;
  200.  
  201.       switch (optc)
  202.     {
  203.     default:
  204.       /* md_parse_option should return 1 if it recognizes optc,
  205.          0 if not.  */
  206.       if (md_parse_option (optc, optarg) != 0)
  207.         break;
  208.       /* `-v' isn't included in the general short_opts list, so check for
  209.          it explicity here before deciding we've gotten a bad argument.  */
  210.       if (optc == 'v')
  211.         {
  212. #ifdef VMS
  213.           /* Telling getopt to treat -v's value as optional can result
  214.          in it picking up a following filename argument here.  The
  215.          VMS code in md_parse_option can return 0 in that case,
  216.          but it has no way of pushing the filename argument back.  */
  217.           if (optarg && *optarg)
  218.         new_argv[new_argc++] = optarg,  new_argv[new_argc] = NULL;
  219.           else
  220. #else
  221.           case 'v':
  222. #endif
  223.           case OPTION_VERBOSE:
  224.         print_version_id ();
  225.           break;
  226.         }
  227.       /*FALLTHRU*/
  228.  
  229.     case '?':
  230.       exit (EXIT_FAILURE);
  231.  
  232.     case 1:            /* File name.  */
  233.       if (!strcmp (optarg, "-"))
  234.         optarg = "";
  235.       new_argv[new_argc++] = optarg;
  236.       new_argv[new_argc] = NULL;
  237.       break;
  238.  
  239.     case OPTION_HELP:
  240.       show_usage (stdout);
  241.       exit (EXIT_SUCCESS);
  242.  
  243.     case OPTION_NOCPP:
  244.       break;
  245.  
  246.     case OPTION_STATISTICS:
  247.       flag_print_statistics = 1;
  248.       break;
  249.  
  250.     case OPTION_VERSION:
  251.       print_version_id ();
  252.       exit (EXIT_SUCCESS);
  253.  
  254.     case OPTION_DUMPCONFIG:
  255.       fprintf (stderr, "alias = %s\n", TARGET_ALIAS);
  256.       fprintf (stderr, "canonical = %s\n", TARGET_CANONICAL);
  257.       fprintf (stderr, "cpu-type = %s\n", TARGET_CPU);
  258. #ifdef TARGET_OBJ_FORMAT
  259.       fprintf (stderr, "format = %s\n", TARGET_OBJ_FORMAT);
  260. #endif
  261. #ifdef TARGET_FORMAT
  262.       fprintf (stderr, "bfd-target = %s\n", TARGET_FORMAT);
  263. #endif
  264.       exit (EXIT_SUCCESS);
  265.  
  266.     case 'J':
  267.       flag_signed_overflow_ok = 1;
  268.       break;
  269.  
  270.     case 'K':
  271.       flag_warn_displacement = 1;
  272.       break;
  273.  
  274.     case 'L':
  275.       flag_keep_locals = 1;
  276.       break;
  277.  
  278.     case 'R':
  279.       flag_readonly_data_in_text = 1;
  280.       break;
  281.  
  282.     case 'W':
  283.       flag_no_warnings = 1;
  284.       break;
  285.  
  286.     case 'Z':
  287.       flag_always_generate_output = 1;
  288.       break;
  289.  
  290.     case 'a':
  291.       if (optarg)
  292.         {
  293.           while (*optarg)
  294.         {
  295.           switch (*optarg)
  296.             {
  297.             case 'd':
  298.               listing |= LISTING_NODEBUG;
  299.               break;
  300.             case 'h':
  301.               listing |= LISTING_HLL;
  302.               break;
  303.             case 'l':
  304.               listing |= LISTING_LISTING;
  305.               break;
  306.             case 'n':
  307.               listing |= LISTING_NOFORM;
  308.               break;
  309.             case 's':
  310.               listing |= LISTING_SYMBOLS;
  311.               break;
  312.             default:
  313.               as_fatal ("invalid listing option `%c'", *optarg);
  314.               break;
  315.             }
  316.           optarg++;
  317.         }
  318.         }
  319.       if (!listing)
  320.         listing = LISTING_DEFAULT;
  321.       break;
  322.  
  323.     case 'D':
  324.       /* DEBUG is implemented: it debugs different */
  325.       /* things from other people's assemblers. */
  326.       flag_debug = 1;
  327.       break;
  328.  
  329.     case 'f':
  330.       flag_no_comments = 1;
  331.       break;
  332.  
  333.     case 'I':
  334.       {            /* Include file directory */
  335.         char *temp = strdup (optarg);
  336.         if (!temp)
  337.           as_fatal ("virtual memory exhausted");
  338.         add_include_dir (temp);
  339.         break;
  340.       }
  341.  
  342.     case 'o':
  343.       out_file_name = strdup (optarg);
  344.       if (!out_file_name)
  345.         as_fatal ("virtual memory exhausted");
  346.       break;
  347.  
  348.     case 'w':
  349.       break;
  350.  
  351.     case 'X':
  352.       /* -X means treat warnings as errors */
  353.       break;
  354.     }
  355.     }
  356.  
  357.   free (shortopts);
  358.   free (longopts);
  359.  
  360.   *pargc = new_argc;
  361.   *pargv = new_argv;
  362. }
  363.  
  364. int 
  365. main (argc, argv)
  366.      int argc;
  367.      char **argv;
  368. {
  369.   int keep_it;
  370.   long start_time = get_run_time ();
  371.  
  372. #ifdef HOST_SPECIAL_INIT
  373.   HOST_SPECIAL_INIT (argc, argv);
  374. #endif
  375.  
  376. #if 0 /* do we need any of this?? */
  377.   {
  378.     static const int sig[] = {SIGHUP, SIGINT, SIGPIPE, SIGTERM, 0};
  379.     int a;
  380.  
  381.     for (a = 0; sig[a] != 0; a++)
  382.       if (signal (sig[a], SIG_IGN) != SIG_IGN)
  383.     signal (sig[a], got_sig);
  384.   }
  385. #endif
  386.  
  387.   myname = argv[0];
  388. #ifndef OBJ_DEFAULT_OUTPUT_FILE_NAME
  389. #define OBJ_DEFAULT_OUTPUT_FILE_NAME "a.out"
  390. #endif
  391.   out_file_name = OBJ_DEFAULT_OUTPUT_FILE_NAME;
  392.  
  393. #ifdef BFD_ASSEMBLER
  394.   bfd_init ();
  395. #endif
  396.  
  397.   symbol_begin ();
  398.   subsegs_begin ();
  399.   read_begin ();
  400.   input_scrub_begin ();
  401.   frag_init ();
  402.   parse_args (&argc, &argv);
  403.  
  404. #ifdef BFD_ASSEMBLER
  405.   output_file_create (out_file_name);
  406.   assert (stdoutput != 0);
  407. #endif
  408.  
  409. #ifdef tc_init_after_args
  410.   tc_init_after_args ();
  411. #endif
  412.  
  413.   perform_an_assembly_pass (argc, argv);    /* Assemble it. */
  414. #ifdef TC_I960
  415.   brtab_emit ();
  416. #endif
  417.  
  418.   if (seen_at_least_1_file ()
  419.       && !((had_warnings () && flag_always_generate_output)
  420.        || had_errors () > 0))
  421.     keep_it = 1;
  422.   else
  423.     keep_it = 0;
  424.  
  425.   if (keep_it)
  426.     write_object_file ();
  427.  
  428. #ifndef NO_LISTING
  429.   listing_print ("");
  430. #endif
  431.  
  432. #ifndef OBJ_VMS /* does its own file handling */
  433. #ifndef BFD_ASSEMBLER
  434.   if (keep_it)
  435. #endif
  436.     output_file_close (out_file_name);
  437. #endif
  438.  
  439.   if (!keep_it)
  440.     unlink (out_file_name);
  441.  
  442.   input_scrub_end ();
  443. #ifdef md_end
  444.   md_end ();
  445. #endif
  446.  
  447.   if (flag_print_statistics)
  448.     {
  449.       extern char **environ;
  450.       char *lim = (char *) sbrk (0);
  451.       long run_time = get_run_time () - start_time;
  452.  
  453.       fprintf (stderr, "%s: total time in assembly: %ld.%06ld\n",
  454.            myname, run_time / 1000000, run_time % 1000000);
  455.       fprintf (stderr, "%s: data size %ld\n",
  456.            myname, (long) (lim - (char *) &environ));
  457.     }
  458.  
  459.   /* Use exit instead of return, because under VMS environments they
  460.      may not place the same interpretation on the value given.  */
  461.   if ((had_warnings () && flag_always_generate_output)
  462.       || had_errors () > 0)
  463.     exit (EXIT_FAILURE);
  464.   exit (EXIT_SUCCESS);
  465. }
  466.  
  467.  
  468. /*            perform_an_assembly_pass()
  469.  *
  470.  * Here to attempt 1 pass over each input file.
  471.  * We scan argv[*] looking for filenames or exactly "" which is
  472.  * shorthand for stdin. Any argv that is NULL is not a file-name.
  473.  * We set need_pass_2 TRUE if, after this, we still have unresolved
  474.  * expressions of the form (unknown value)+-(unknown value).
  475.  *
  476.  * Note the un*x semantics: there is only 1 logical input file, but it
  477.  * may be a catenation of many 'physical' input files.
  478.  */
  479. static void 
  480. perform_an_assembly_pass (argc, argv)
  481.      int argc;
  482.      char **argv;
  483. {
  484.   int saw_a_file = 0;
  485. #ifdef BFD_ASSEMBLER
  486.   flagword applicable;
  487. #endif
  488.  
  489.   need_pass_2 = 0;
  490.  
  491. #ifndef BFD_ASSEMBLER
  492. #ifdef MANY_SEGMENTS
  493.   {
  494.     unsigned int i;
  495.     for (i = SEG_E0; i < SEG_UNKNOWN; i++)
  496.       segment_info[i].fix_root = 0;
  497.   }
  498.   /* Create the three fixed ones */
  499.   {
  500.     segT seg;
  501.  
  502. #ifdef TE_APOLLO
  503.     seg = subseg_new (".wtext", 0);
  504. #else
  505.     seg = subseg_new (".text", 0);
  506. #endif
  507.     assert (seg == SEG_E0);
  508.     seg = subseg_new (".data", 0);
  509.     assert (seg == SEG_E1);
  510.     seg = subseg_new (".bss", 0);
  511.     assert (seg == SEG_E2);
  512. #ifdef TE_APOLLO
  513.     create_target_segments ();
  514. #endif
  515.   }
  516.  
  517. #else /* not MANY_SEGMENTS */
  518.   text_fix_root = NULL;
  519.   data_fix_root = NULL;
  520.   bss_fix_root = NULL;
  521. #endif /* not MANY_SEGMENTS */
  522. #else /* BFD_ASSEMBLER */
  523.   /* Create the standard sections, and those the assembler uses
  524.      internally.  */
  525.   text_section = subseg_new (".text", 0);
  526.   data_section = subseg_new (".data", 0);
  527.   bss_section = subseg_new (".bss", 0);
  528.   /* @@ FIXME -- we're setting the RELOC flag so that sections are assumed
  529.      to have relocs, otherwise we don't find out in time. */
  530.   applicable = bfd_applicable_section_flags (stdoutput);
  531.   bfd_set_section_flags (stdoutput, text_section,
  532.              applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC
  533.                        | SEC_CODE | SEC_READONLY));
  534.   /* @@ FIXME -- SEC_CODE seems to mean code only, rather than code possibly.*/
  535.   bfd_set_section_flags (stdoutput, data_section,
  536.              applicable & (SEC_ALLOC | SEC_LOAD | SEC_RELOC));
  537.   bfd_set_section_flags (stdoutput, bss_section, applicable & SEC_ALLOC);
  538.   seg_info (bss_section)->bss = 1;
  539.   subseg_new (BFD_ABS_SECTION_NAME, 0);
  540.   subseg_new (BFD_UND_SECTION_NAME, 0);
  541.   reg_section = subseg_new ("*GAS `reg' section*", 0);
  542.   expr_section = subseg_new ("*GAS `expr' section*", 0);
  543.  
  544. #endif /* BFD_ASSEMBLER */
  545.  
  546.   subseg_set (text_section, 0);
  547.  
  548.   /* This may add symbol table entries, which requires having an open BFD,
  549.      and sections already created, in BFD_ASSEMBLER mode.  */
  550.   md_begin ();
  551.  
  552.   argv++;            /* skip argv[0] */
  553.   argc--;            /* skip argv[0] */
  554.   while (argc--)
  555.     {
  556.       if (*argv)
  557.     {            /* Is it a file-name argument? */
  558.       saw_a_file++;
  559.       /* argv->"" if stdin desired, else->filename */
  560.       read_a_source_file (*argv);
  561.     }
  562.       argv++;            /* completed that argv */
  563.     }
  564.   if (!saw_a_file)
  565.     read_a_source_file ("");
  566. }                /* perform_an_assembly_pass() */
  567.  
  568. #if 0
  569. /* This is not currently used.  */
  570. static SIGTY
  571. got_sig (sig)
  572.      int sig;
  573. {
  574.   static here_before = 0;
  575.  
  576.   as_bad ("Interrupted by signal %d", sig);
  577.   if (here_before++)
  578.     exit (EXIT_FAILURE);
  579. #if 0 /* If SIGTY is void, this produces warnings.  */
  580.   return ((SIGTY) 0);
  581. #endif
  582. }
  583. #endif
  584.  
  585. /* end of as.c */
  586.